#include <chrono>
#include <random>
#include <fstream>
#include <utility>

#include "macros/errors.h"
#include "backend/program/program_mainc_group.h"
// #include "backend/kernel_interface/kernel_scheduler.h"
#include "backend/program/program_impl_mainc_group.h"

namespace txdnn {
namespace backend {

/* class ProgramMainCGroup implementation*/

ProgramMainCGroup::ProgramMainCGroup() {}
ProgramMainCGroup::ProgramMainCGroup(const fs::path& program_path,
                                     std::string params,
                                     const TargetProperties& target,
                                     const std::string& kernel_src) 
  : impl_(std::make_shared<ProgramImplMainCGroup>(program_path, params, target, kernel_src)) {}

ProgramMainCGroup::ProgramMainCGroup(const fs::path& program_path, const fs::path& bin_file) 
  : impl_(std::make_shared<ProgramImplMainCGroup>(program_path, bin_file)) {}

ProgramMainCGroup::ProgramMainCGroup(const fs::path& program_path, const std::vector<char>& bin_file) 
  : impl_(std::make_shared<ProgramImplMainCGroup>(program_path, bin_file)) {}

ProgramMainCGroup::ProgramMainCGroup(const fs::path& program_path, const std::vector<uint8_t>& bin_file) 
  : impl_(std::make_shared<ProgramImplMainCGroup>(program_path, bin_file)) {}

// txdaModule_t ProgramMainCGroup::getModule() const { return impl_->module_.get(); }

fs::path ProgramMainCGroup::getCodeObjectPathName() const {
  if (!impl_->bin_file_.empty()) {
    TXDNN_THROW("Failed to get object path, bin_file_ is empty.");
  }
  return impl_->bin_file_;
}

const std::vector<char>& ProgramMainCGroup::getCodeObjectBlob() const { return impl_->binary_; }

bool ProgramMainCGroup::isCodeObjectInMemory() const { return !impl_->binary_.empty(); }
bool ProgramMainCGroup::isCodeObjectInFile() const { return !impl_->bin_file_.empty(); }
bool ProgramMainCGroup::isCodeObjectInTempFile() const { return !impl_->dir_.has_value(); }

void ProgramMainCGroup::freeCodeObjectFileStorage() {
  if (impl_->dir_.has_value()) {
    impl_->dir_.reset();
    impl_->bin_file_.clear();
  }
}

void ProgramMainCGroup::attachBinary(std::vector<char> binary) { impl_->binary_ = std::move(binary); }
void ProgramMainCGroup::attachBinary(fs::path binary) {
  if (impl_->bin_file_ != binary) {
    impl_->dir_ = std::nullopt;
  }
  impl_->bin_file_ = std::move(binary);
}



} // namespace backend
} // namespace txdnn